/*
 * =====================================================================================
 *
 *       Filename:  globals.hpp
 *
 *    Description:  
 *
 *        Version:  0.1a
 *        Created:  17.05.2012 22:05:10
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Waldemar Gorbunov,
 *   Organization:  
 *
 * =====================================================================================
 */

#include "globals.hpp"

namespace Drosera {

// fatal error messeg on the screen

void error ( const char * msg ) {
	std::cout << "[ERROR] " << msg << std::endl;
	writelog ( msg );
	exit(1);
}

// warning messeg on the screen

void warning ( const char * msg ) {
	std::cout << "[WARNING] " << msg << std::endl;
	writelog ( msg );
}

// info messeg on the screen

void info ( const char * msg ) {
	std::cout << "[INFO] " << msg << std::endl;
	writelog ( msg );
}


void error ( const char * msg, int error ) {
	std::cout << "[ERROR] " << msg << " - " << error << std::endl;
	writelog ( msg );
	exit(1);
}

// warning messeg on the screen

void warning ( const char * msg, int warning ) {
	std::cout << "[WARNING] " << msg << " - " << warning  <<  std::endl;
	writelog ( msg );
}

// info messeg on the screen

void info ( const char * msg, int info ) {
	std::cout << "[INFO] " << msg << " - " << info << std::endl;
	writelog ( msg );
}
// writes a log-file

void writelog ( const char * msg ) {

	static std::mutex mutex;
	time_t rawtime;
	struct tm * timeinfo;
	char buffer[80];

	time ( &rawtime );
	timeinfo = localtime ( &rawtime );

	strftime ( buffer, 80 , "[%H:%M:%S]", timeinfo );

	mutex.lock();
	
	std::fstream pfile ( LOGFILE, std::fstream::out | std::fstream::app );
	pfile << buffer << msg << std::endl;
	pfile.close();

	mutex.unlock();
}

// Generates an uniqueID of size X

std::string uniqueId ( unsigned short size ) {

	char rtn[size+1];	
	static const char alphanum[] =
		"0123456789"
		"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
		"abcdefghijklmnopqrstuvwxyz";

    	for ( unsigned short i = 0; i < size; ++i )
		rtn[i] = alphanum[ rand() % ( sizeof( alphanum ) - 1 ) ];
	
	rtn[size] = 0;
	return std::string ( rtn );
}

// saves / return the global args - maybe necessery

char **globalArgs ( char **args ) {
	static char **argv = NULL;
	if ( args == NULL )
		return argv;
	else
		argv = args;
}

// Reap the child process

void reap_child ( int num ) {

	sigset_t set, oldset;
	pid_t pid;
	int status, exitstatus;

  /* block other incoming SIGCHLD signals */
	sigemptyset(&set);
	sigaddset(&set, SIGCHLD);
	sigprocmask(SIG_BLOCK, &set, &oldset);
	
	while((pid = waitpid((pid_t)-1, &status, WNOHANG)) > 0){

		if(WIFEXITED(status)){
			exitstatus = WEXITSTATUS(status);
			info ( "Parend: Child exited" );
		}
		else if(WIFSIGNALED(status)){
			exitstatus = WTERMSIG(status);
			info ( "Parend: Child terminated" );
		}
		else if(WIFSTOPPED(status)){
			exitstatus = WSTOPSIG(status);
			info ( "Parend: Child stopped" );
		}
		else{
			info ( "Parent: Child stopped magicly" );
		}
	}

	signal(SIGCHLD, reap_child);
	sigemptyset(&set);
	sigaddset(&set, SIGCHLD);
	sigprocmask(SIG_UNBLOCK, &set, &oldset);

}

// Check if file exists or not

bool fileExist ( char *path ) {

	std::fstream file ( path, std::fstream::in );

	if ( file.good() ) {
		file.close();
		return true;
	}
	file.close();
	return false;
}

static ssize_t get_size ( int fd ) {
    struct stat statbuf;
    if ( fstat ( fd, &statbuf ) < 0 ) return -1;
    return statbuf.st_size;
}

std::string getMD5 ( char* path ) {
	std::string ret;
	unsigned char md5[MD5_DIGEST_LENGTH];
	char buf[1];
	char *fbuf;
	ssize_t fsize;
	
	int fd = open ( path, O_RDONLY );
	
	fsize = get_size ( fd );
	fbuf = ( char* ) mmap ( 0, fsize, PROT_READ, MAP_SHARED, fd, 0 );
	MD5 ( ( unsigned char* ) fbuf, fsize, md5 );

	for ( int x = 0; x < 16; x++ ) {
		sprintf ( buf, "%02x", md5[x] );
		ret += buf;
	}
	return ret;
}

}
